/*******************************************************************************
 Chatty - Mobile Messaging - J2ME ICQ clone
 Copyright (C) 2003-05  Chatty Project

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 ********************************************************************************
 File: src/chatty/SplashCanvas.java
 Version: ###VERSION###  Date: ###DATE###
 Author(s): Manuel Linsmayer, Andreas Rossbacher, Vladimir Kryukov
 *******************************************************************************/


package chatty;

import DrawControls.*;
import DrawControls.icons.*;
import DrawControls.text.Par;
import DrawControls.text.Parser;

import java.util.*;
import java.io.IOException;
import javax.microedition.lcdui.*;

import chatty.comm.*;
import chatty.chat.message.Message;
import chatty.cl.*;
import chatty.modules.*;
import chatty.ui.*;
import chatty.ui.base.*;
import chatty.ui.timers.*;
import chatty.util.*;

import protocol.*;


public final class SplashCanvas extends CanvasEx {	
	
    // True if keylock has been enabled
    static private final short KEY_LOCK_MSG_TIME = 2000 / NativeCanvas.UIUPDATE_TIME;
    static private final short UPDATE_INTERVAL = 20000 / NativeCanvas.UIUPDATE_TIME;
    static private final short RESET_INTERVAL = 3000 / NativeCanvas.UIUPDATE_TIME;

    private final Image splash = ImageList.loadImage("/logo.png");

	// Font used to display the logo (if image is not available)
	private final Font logoFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
	
	// Font used to display the version nr
	private final Font versionFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);

	// Font used to display informational messages
	private final Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);

	/*****************************************************************************/
    private short keyLock = -1;
    private short updateTime = UPDATE_INTERVAL;
    private short resetTime = -1;


    // Message to display beneath the splash image
    private Icon statusImg;
    private String message;
    private Progress process;
    
    // Progress in percent
    private volatile int progress;
    
    // Number of available messages
    private int availableMessages;
    
    // Time since last key # pressed
    private long poundPressTime;
    
	public static final SplashCanvas instance = new SplashCanvas();

	private SplashCanvas() {
	}
	// Sets the informational message
	static public void setMessage(String message) {
		instance.message = message;
        instance.statusImg = null;
        instance.progress = 0;
        instance.invalidate();
	}

	public static void setStatusToDraw(Icon img) {
		instance.statusImg = img;
	}

	public static void setNotifyMessage(Icon img, String msg) {
		instance.statusImg = img;
		instance.message = msg;
        instance.resetTime = RESET_INTERVAL;
        instance.invalidate();
    }
    public static void showSplash() {
        instance.show();
    }
    
    // Sets the current progress in percent (and request screen refresh)
    static public void setProgress(int progress) {
        if (progress == instance.progress) return;
        instance.progress = progress;
        NativeCanvas.getInstance().updateMetrix();
        instance.invalidate();
    }
    
    private void setLockMessage() {
        setMessage(ResBundle.getString("keylock_enabled"));
        setStatusToDraw(null);
    }
    public void lockChatty() {
        keyLock = 0;
        process = null;
        setLockMessage();
        messageAvailable();
        show();
    }


    // Called when message has been received
    public static void messageAvailable() {
        if (Chatty.isLocked()) {
            int unread = ContactList.getInstance().getUnreadMessCount();
            if (unread != instance.availableMessages) {
                instance.availableMessages = unread;
                instance.invalidate();
            }
        }
    }
    protected void stylusTap(int x, int y, boolean isLongTap) {
        int height = Math.max(getProgressHeight(), minItemHeight);
        int minY = getH() - height;
        if (minY < y) {
            int region = getW() * 2 / 3;
            if (region < x) {
                closeAnyAction();
            }
        }
    }
    
    protected void stylusXMoving(int fromX, int fromY, int toX, int toY) {
        if (Chatty.isLocked()) {
            int region = Math.max(getProgressHeight(), minItemHeight);
            int minY = getH() - region;
            if ((fromY < minY) || (toY < minY)) {
                poundPressTime = 0;
                keyLock = KEY_LOCK_MSG_TIME;
                setProgress(0);
                invalidate();
                return;
            }
            int x1 = Math.min(fromX, toX);
            int x2 = Math.max(fromX, toX);
            setProgress(x2 * 100 / getW());
        }
    }
    protected void stylusXMoved(int fromX, int fromY, int toX, int toY) {
        int region = Math.max(getProgressHeight(), minItemHeight);
        int minY = getH() - region;
        if ((fromY < minY) || (toY < minY)) {
            poundPressTime = 0;
            keyLock = KEY_LOCK_MSG_TIME;
            setProgress(0);
            invalidate();
            return;
        }
        int x1 = Math.min(fromX, toX);
        int x2 = Math.max(fromX, toX);
        if ((x1 < region) && (getW() - region < x2)) {
            if (Chatty.isLocked()) {
                Chatty.unlockChatty();
                return;
            }
            ContactList.activateContactList();
        } else {
            setProgress(0);
        }
    }
    private void closeAnyAction() {
        Progress p = process;
        if (null != p) {
            p.closeAnyAction();
        }
    }
    // Called when a key is pressed
    protected void doKeyReaction(int keyCode, int actionCode, int type) {
        if (Chatty.isLocked() && (Canvas.KEY_POUND == keyCode)) {
            long now = System.currentTimeMillis();
            
            if ((KEY_PRESSED == type) && (0 == poundPressTime)) {
                poundPressTime = now;
            } else if (0 < poundPressTime) {
                long delta = now - poundPressTime;
                long max = 1000;
                if (delta > max * 2) {
                    delta = 0;
                    poundPressTime = 0;
                }
                setProgress((int)Math.min(delta * 100 / max, 100));
                if (delta > max) {
                    Chatty.unlockChatty();
                    poundPressTime = 0;
                }
            }
            return;
        }
        if (KEY_PRESSED == type) {
            if (Chatty.isLocked()) {
                setProgress(0);
                poundPressTime = 0;
                keyLock = KEY_LOCK_MSG_TIME;
                invalidate();
            
            } else {
                if (NativeCanvas.RIGHT_SOFT == keyCode) {
                    closeAnyAction();

                // #sijapp cond.if modules_DEBUGLOG is "true" #
                } else if ((Canvas.KEY_POUND == keyCode)) {
                    ContactList.activateContactList();
                // #sijapp cond.end#
                }
            }
        }
    }
    
    protected void updateTask() {
        boolean repaintIt = false;
        if (0 <= resetTime) {
            if (0 == resetTime) {
                setLockMessage();
                repaintIt = true;
            }

            resetTime--;
        }
        
        // key lock
        if (0 <= keyLock) {
            if (0 == keyLock) {
                repaintIt = true;
            }
            keyLock--;
        }
        
        // clock
        if (0 <= updateTime) {
            updateTime--;
            if (0 > updateTime) {
                updateTime = UPDATE_INTERVAL;
                repaintIt = true;
            }
        }

        // locking
        if (0 < poundPressTime) {
            long now = System.currentTimeMillis();
            long delta = now - poundPressTime;
            long max = 1000;
            if (delta > max * 2) {
                delta = 0;
                poundPressTime = 0;
            }
            setProgress((int)Math.min(delta * 100 / max, 100));
        }
        
        if (repaintIt) {
            invalidate();
        }
    }


    private void showMessage(GraphicsEx g, String msg, int width, int height) {
        final int size_x = width / 10 * 8;
        final int textWidth = size_x - 8;

        Font[] fontSet = GraphicsEx.chatFontSet;
        Parser parser = new Parser(-1, fontSet, textWidth);
        parser.addText(msg, THEME_SPLASH_LOCK_TEXT, FONT_STYLE_PLAIN);
        Par par = parser.getPar();

        final int textHeight = par.getHeight();
        final int size_y = textHeight + 8;
        final int x = width / 2 - (width / 10 * 4);
        final int y = height / 2 - (size_y / 2);
        g.setThemeColor(THEME_SPLASH_LOCK_BACK);
        g.fillRect(x, y, size_x, size_y);
        g.setThemeColor(THEME_SPLASH_LOCK_TEXT);
        g.drawRect(x + 2, y + 2, size_x - 5, size_y - 5);
        g.setThemeColor(THEME_SPLASH_LOCK_TEXT);
        par.paint(fontSet, g, x + 4, y + 4, 0, textHeight, false);
    }

    private int getH() {
        return getScreenHeight();
    }
    private int getW() {
        return getScreenWidth();
    }
    // Render the splash image
    protected void paint(GraphicsEx g) {
        final int height = getH();
        final int width  = getW();
        final int fontHeight = font.getHeight();
        // Do we need to draw the splash image?
        if (g.getClipY() < height - fontHeight - 2) {
            // Draw background
            g.setThemeColor(THEME_SPLASH_BACKGROUND);
            g.fillRect(0, 0, width, height);

            // Display splash image (or text)
            if (null != splash) {
                g.drawImage(splash, width / 2, height / 2, Graphics.HCENTER | Graphics.VCENTER);
            } else {
                g.setThemeColor(THEME_SPLASH_LOGO_TEXT);
                g.setFont(logoFont);
                g.drawString("chatty", width / 2, height / 2 + 5, Graphics.HCENTER | Graphics.BASELINE);
                g.setFont(font);
            }
            
            // Draw the date
            g.setThemeColor(THEME_SPLASH_DATE);
            g.setFont(font);
            g.drawString(Util.getDateString(false), width / 2, 12, Graphics.TOP | Graphics.HCENTER);
            g.drawString(Util.getCurrentDay(), width / 2, 13 + font.getHeight(),
                    Graphics.TOP | Graphics.HCENTER);

            // Display message icon, if keylock is enabled
            if (Chatty.isLocked()) {
                if (0 < availableMessages) {
                    Icon icon = Message.msgIcons.iconAt(Message.ICON_MSG_NONE);
                    if (null != icon) {
                        g.drawByLeftTop(icon, 1, height - (2 * fontHeight) - 9);
                    }
                    g.setThemeColor(THEME_SPLASH_MESSAGES);
                    g.setFont(font);
                    int x = Message.msgIcons.getWidth() + 4;
                    int y = height - (2 * fontHeight) - 5;
                    g.drawString("# " + availableMessages, x, y, Graphics.LEFT | Graphics.TOP);
                }

                // Display the keylock message if someone hit the wrong key
                if (0 < keyLock) {
                    // Init the dimensions
                    String lockMsg = ResBundle.getString("keylock_message");
                    showMessage(g, lockMsg, width, height);
                }
            }
        }
        
        final int im_width = (null == statusImg) ? 0 : statusImg.getWidth();
        int progressHeight = getProgressHeight();
        int stringWidth = font.stringWidth(message);
        g.setFont(font);

        // Draw white bottom bar
        g.setThemeColor(THEME_SPLASH_PROGRESS_BACK);
        //g.setStrokeStyle(Graphics.DOTTED);
        g.drawLine(0, height - progressHeight - 3, width, height - progressHeight - 3);

        g.setThemeColor(THEME_SPLASH_PROGRESS_BACK);
        g.drawString(message, (width / 2) + (im_width / 2), height, Graphics.BOTTOM | Graphics.HCENTER);
        if (null != statusImg) {
            g.drawInCenter(statusImg, (width / 2) - (stringWidth / 2),
                    height - (progressHeight / 2));
        }

        // Draw current progress
        int progressPx = width * progress / 100;
        if (progressPx < 1) return;
        g.setClip(0, height - progressHeight - 2, progressPx, progressHeight + 2);

        g.setThemeColor(THEME_SPLASH_PROGRESS_BACK);
        g.fillRect(0, height - progressHeight - 2, progressPx, progressHeight + 2);

        g.setThemeColor(THEME_SPLASH_PROGRESS_TEXT);
        // Draw the progressbar message
        g.drawString(message, (width / 2) + (im_width / 2), height, Graphics.BOTTOM | Graphics.HCENTER);
        if (null != statusImg) {
            g.drawInCenter(statusImg, (width / 2) - (stringWidth / 2),
                    height - (progressHeight / 2));
        }
    }
    private int getProgressHeight() {
        final int fontHeight = font.getHeight();
        if (null != statusImg) {
            return Math.max(fontHeight, statusImg.getHeight());
        }
        return fontHeight;
    }
    
    public static void setProgressBar(Progress p) {
        instance.process = p;
    }
}
